package proj;

import java.io.FileReader;
import java.io.LineNumberReader;
import java.util.Random;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.functions.MultilayerPerceptron;
import weka.classifiers.rules.NNge;
import weka.classifiers.trees.J48;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;

public class Main {

	public static int CLASSIFIER = 1;
	
//	public static Classifier kstar(String[] args, int curArg) throws Exception {
//		KStar kstar = new KStar();
//		System.out.println("#" + args[CLASSIFIER]);
//		return kstar;
//	}
	
	public static Classifier knn(String[] args, int curArg) throws Exception {
		NNge nnge = new NNge();
		System.out.println("#" + args[CLASSIFIER]);
		return nnge;
	}
	
	public static Classifier naiveBayseian(String[] args, int curArg)
			throws Exception {
		NaiveBayes nb = new NaiveBayes();
		System.out.println("#" + args[CLASSIFIER]);
		return nb;
	}

	public static Classifier decisionTree(String[] args, int curArg)
			throws Exception {
		J48 nb = new J48();
		System.out.println("#" + args[CLASSIFIER]);
		return nb;
	}

	public static Classifier neuralNetwork(String[] args, int curArg)
			throws Exception {

		String learningRate = null;
		String momentum = null;
		String numberHiddenNeurons = null;
		String numberEpochs = null;

		learningRate = args[curArg++];
		momentum = args[curArg++];
		numberHiddenNeurons = args[curArg++];
		numberEpochs = args[curArg++];

		String[] options = new String[8];
		options[0] = "-L"; // Learning Rate
		options[1] = learningRate;
		options[2] = "-M"; // Momentum
		options[3] = momentum;
		options[4] = "-H"; // Number of hidden layer neurons
		options[5] = numberHiddenNeurons;
		options[6] = "-N"; // Number of epochs
		options[7] = numberEpochs;

		System.out.println("#" + args[CLASSIFIER] + " " + learningRate + " " + momentum
				+ " " + numberHiddenNeurons + " " + numberEpochs);

		MultilayerPerceptron scheme = new MultilayerPerceptron();
		scheme.setOptions(options);
		return scheme;
	}

	public static void main(String[] args) throws Exception {

		// Use: java Main ARFF_FILE CLASSIFIER KFOLD CLASSIFIER_PARAM  

		DataSource source = new DataSource(args[0]);
		Instances data = source.getDataSet();
		data.setClassIndex(data.numAttributes() - 1);
		
		Classifier scheme = null;
		
		if (args[CLASSIFIER].equals("NN")) {
			scheme = neuralNetwork(args, 3);
		} else if (args[CLASSIFIER].equals("NB")) {
			scheme = naiveBayseian(args, 3);
		} else if (args[CLASSIFIER].equals("DT")) {
			scheme = decisionTree(args, 3);
		} else if (args[CLASSIFIER].equals("KN")) {
			scheme = knn(args, 3);
		//} else if (args[CLASSIFIER].equals("KS")) {
		//	scheme = kstar(args, 3);
		} else if (args[CLASSIFIER].equals("N")) {
			LineNumberReader lnr = new LineNumberReader(new FileReader(args[0]));
			int correct = 0;
			int incorrect = 0;
			while (lnr.ready()) {
				String line = lnr.readLine();
				if (line.endsWith("0,0") || line.endsWith("1,1")) {
					correct++;
				}
				if (line.endsWith("0,1") || line.endsWith("1,0")) {
					incorrect++;
				}
			}
			System.out.println("#N");
			System.out.println(correct + " " + incorrect);
			System.exit(0);
		} else {
			throw new RuntimeException(args[1]);
		}

		int kFold = Integer.parseInt(args[2]);

		Evaluation eval = new Evaluation(data);
		long before = System.currentTimeMillis();
		eval.crossValidateModel(scheme, data, kFold, new Random());
		long time = System.currentTimeMillis() - before;
		System.out.println(eval.correct() + " " + eval.incorrect() + " "
				+ eval.kappa() + " " + eval.meanAbsoluteError() + " "
				+ eval.rootMeanSquaredError() + " "
				+ eval.relativeAbsoluteError() + " "
				+ eval.rootRelativeSquaredError() + " " + eval.numInstances()
				+ " " + time);
	}
}
